package org.jflame.uid.worker.dao.impl;

import org.jflame.uid.worker.dao.IWorkerNodeDao;
import org.jflame.uid.worker.entity.WorkerNodeEntity;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.transaction.annotation.Transactional;

public class WorkerNodeJdbcImpl implements IWorkerNodeDao {

    private JdbcTemplate jdbcTemplate;

    public WorkerNodeJdbcImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    private static final String SQL_QUERY = "SELECT id,host_name,port,node_type,launch_date,modified,created FROM worker_node WHERE host_name=? AND port=?";

    @Override
    public WorkerNodeEntity getWorkerNodeByHostPort(String host, String port) {
        List<WorkerNodeEntity> lst = jdbcTemplate.query(SQL_QUERY, new Object[] { host,port },
                BeanPropertyRowMapper.newInstance(WorkerNodeEntity.class));
        if (lst != null && !lst.isEmpty()) {
            return lst.get(0);
        }
        return null;
    }

    private static final String SQL_ADD = "INSERT INTO worker_node(host_name,port,node_type,launch_date,modified,created) VALUES(?,?,?,?,?,?)";

    @Override
    @Transactional
    public boolean registerWorkerNode(WorkerNodeEntity worker) {
        KeyHolder holder = new GeneratedKeyHolder();
        int i = jdbcTemplate.update(new PreparedStatementCreator() {

            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(SQL_ADD, Statement.RETURN_GENERATED_KEYS);
                ps.setString(1, worker.getHostName());
                ps.setString(2, worker.getPort());
                ps.setInt(3, worker.getNodeType());
                ps.setTimestamp(4, asTimestamp(worker.getLaunchDate()));
                Timestamp now = asTimestamp(new Date());
                ps.setTimestamp(5, now);
                ps.setTimestamp(6, now);
                return ps;
            }
        }, holder);

        if (i > 0) {
            int newId = holder.getKey()
                    .intValue();
            worker.setId(newId);
            return true;
        }
        return false;
    }

    java.sql.Timestamp asTimestamp(Date dt) {
        return new Timestamp(dt.getTime());
    }

}
